package com.sky.service.impl;

import com.sky.constant.StatusConstant;
import com.sky.entity.Orders;
import com.sky.mapper.*;
import com.sky.service.WorkSpaceService;
import com.sky.vo.BusinessDataVO;
import com.sky.vo.DishOverViewVO;
import com.sky.vo.OrderOverViewVO;
import com.sky.vo.SetmealOverViewVO;
import lombok.SneakyThrows;
import org.apache.poi.xssf.usermodel.*;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Objects;

/**
 * PROJECT_NAME: sky-take-out
 * NAME: WorkSpaceServiceImpl
 * USER: SHINIAN
 * DATE: 2022/12/12
 * DESCRIPTION : B端-工作台信息服务层接口实现类
 */
@Service
public class WorkSpaceServiceImpl implements WorkSpaceService {

    //注入订单持久层实现类Bean
    @Resource
    private OrderMapper ordersMapper;
    //注入用户持久层实现类Bean
    @Resource
    private UserMapper userMapper;
    //注入菜品持久层实现类Bean
    @Resource
    private DishMapper dishMapper;
    //注入套餐持久层实现类Bean
    @Resource
    private SetMealMapper setmealMapper;
    @Resource
    private ReportMapper reportMapper;
    @Resource
    private WorkSpaceService workSpaceService;
    /**
     * 查询指定时间段销售与用户数据
     * <p>
     * BusinessDataVO包含内容:
     * - turnover : 今日销售额
     * - validOrderCount : 今日有效订单数量
     * - orderCompletionRate : 今日订单完成率
     * - unitPrice : 今日平均客单价
     * - newUsers : 今日新增长用户数
     *
     * @param startTime 开始统计时间
     * @param endTime   结束统计时间
     * @return 指定时间段销售与用户数据Bean
     */
    @Override
    public BusinessDataVO selectBusinessData(LocalDateTime startTime, LocalDateTime endTime) {
        //基于订单持久层查询今日销售额与今日有效订单数量
        Double thisDayAmount = reportMapper.turnoverReport(Orders.COMPLETED, startTime, endTime);
        if (Objects.isNull(thisDayAmount))
            thisDayAmount = 0.0; //如果今日没有销售额则默认为NULL手动修改为0.0
        Integer thisDayCompletedOrderCount = reportMapper.fordersReport(Orders.COMPLETED, startTime, endTime);
        if (Objects.isNull(thisDayCompletedOrderCount))
            thisDayCompletedOrderCount = 0; //如果今天没有有效订单则默认为NULL手动修改为0
        Integer thisDayOrderCount = reportMapper.fordersReport(null, startTime, endTime);
        //完成今日平均客单价与订单完成率的声明和计算
        Double unitPrice = 0.0;
        Double orderCompletionRate = 0.0;
        if (thisDayOrderCount != 0 && thisDayCompletedOrderCount != 0) {
            unitPrice = thisDayAmount / thisDayCompletedOrderCount;
            DecimalFormat decimalFormat = new DecimalFormat("#.00");
            unitPrice = Double.parseDouble(decimalFormat.format(unitPrice));
            orderCompletionRate = thisDayCompletedOrderCount * 1.0 / thisDayOrderCount;
        }
        //计算新增用户数
        Integer newUserCount = userMapper.selectCountByTime(startTime, endTime);
        return BusinessDataVO.builder()
                .newUsers(newUserCount)
                .turnover(thisDayAmount)
                .unitPrice(unitPrice)
                .validOrderCount(thisDayCompletedOrderCount)
                .orderCompletionRate(orderCompletionRate).build();
    }

    /**
     * 查询今日订单数量数据
     * <p>
     * OrderOverViewVO包括:
     * - waitingOrders : 待接单订单数量
     * - deliveredOrders : 派送中订单数量
     * - completedOrders : 已完成订单数量
     * - cancelledOrders : 已取消订单数量
     * - allOrders : 总订单数量
     *
     * @return 今日订单数量数据
     */
    @Override
    public OrderOverViewVO selectOrdersOverview() {
        //封装表示今日开始时间/结束时间的日期对象
        LocalDateTime thisDayStartTime = LocalDateTime.now().with(LocalTime.MIN);
        LocalDateTime thisDayEndTime = LocalDateTime.now().with(LocalTime.MAX);
        //基于订单持久层查询今日不同状态的订单数量
        Integer waitingOrders = reportMapper.fordersReport(Orders.TO_BE_CONFIRMED, thisDayStartTime, thisDayEndTime);
        Integer deliveredOrders = reportMapper.fordersReport(Orders.CONFIRMED, thisDayStartTime, thisDayEndTime);
        Integer completedOrders =reportMapper.fordersReport (Orders.COMPLETED, thisDayStartTime, thisDayEndTime);
        Integer cancelledOrders =reportMapper.fordersReport (Orders.CANCELLED, thisDayStartTime, thisDayEndTime);
        Integer allOrders =reportMapper.fordersReport (null, thisDayStartTime, thisDayEndTime);
        return OrderOverViewVO.builder()
                .waitingOrders(waitingOrders)
                .deliveredOrders(deliveredOrders)
                .completedOrders(completedOrders)
                .cancelledOrders(cancelledOrders)
                .allOrders(allOrders).build();
    }

    /**
     * 查询菜品状态数据
     * <p>
     * DishOverViewVO包含:
     * - sold : 已启售菜品数量
     * - discontinued : 已停售菜品数量
     *
     * @return 全局通用返回信息Bean(菜品状态数据Bean)
     */
    @Override
    public DishOverViewVO selectDishOverView() {
        //基于菜品持久层查询不同状态菜品数量
        Integer soldDishCount = dishMapper.selectDishCountByStatus(StatusConstant.ENABLE);
        Integer discontinuedDishCount = dishMapper.selectDishCountByStatus(StatusConstant.DISABLE);
        return DishOverViewVO.builder().sold(soldDishCount).discontinued(discontinuedDishCount).build();
    }

    /**
     * 查询套餐状态数据
     * <p>
     * SetmealOverViewVO包含:
     * - sold : 已启售套餐数量
     * - discontinued : 已停售套餐数量
     *
     * @return 全局通用返回信息Bean(套餐状态数据Bean)
     */
    @Override
    public SetmealOverViewVO selectSetmealOverView() {
        //调用套餐持久层查询不同状态的套餐数量
        Integer soldSetmealCount = setmealMapper.selectSetmealCOuntByStatus(StatusConstant.ENABLE);
        Integer discontinuedSetmealCount = setmealMapper.selectSetmealCOuntByStatus(StatusConstant.DISABLE);
        return SetmealOverViewVO.builder().sold(soldSetmealCount).discontinued(discontinuedSetmealCount).build();
    }
    //导出30天内容
    @SneakyThrows
    @Override
    public void export30DBusinessDate(HttpServletResponse httpServletResponse)  {
        //(1)获取要读取的运营数据报表.xlsx文件
        //is:绑定了当前项目resources下template文件夹中运营数据报表.xlsx的字节输入流
        InputStream is = this.getClass().getClassLoader().getResourceAsStream("template\\\\运营数据报表.xlsx");
        //(2)将is绑定的文件内容读取到一个XSSFWorkBook
        XSSFWorkbook xssfWorkbook = new XSSFWorkbook(is);
        XSSFSheet sheet1 = xssfWorkbook.getSheetAt(0);
        //创建格式剧中
        XSSFCellStyle cellStyle = xssfWorkbook.createCellStyle();
        cellStyle.setAlignment(XSSFCellStyle.ALIGN_CENTER);
        //(3)完成部分1的内容声明 声明当前数据报表的数据从哪一天到哪一天(近30天) 获取表示30天的日期对象和昨天的日期对象形成一个日期区间
        LocalDate startDate = LocalDate.now().minusDays(30);
        LocalDate endDate = LocalDate.now().minusDays(1);

        //指定输出日期格式
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
        String startDateString = dateTimeFormatter.format(startDate);
        String endDateString = dateTimeFormatter.format(endDate);
        //开始内存中excel表格写入值
        sheet1.getRow(1).getCell(1).setCellValue(startDateString+"至"+endDateString);
        //(4)完成部分2的内容声明 计算从startDate 00:00:00开始到endDate 23:59:59秒之间的运营数据
        BusinessDataVO businessDataVO = workSpaceService.selectBusinessData(LocalDateTime.of(startDate, LocalTime.MIN), LocalDateTime.of(endDate, LocalTime.MAX));
        //营业额
        sheet1.getRow(3).getCell(2).setCellValue(businessDataVO.getTurnover());
        //订单完成率
        sheet1.getRow(3).getCell(4).setCellValue(businessDataVO.getOrderCompletionRate());
        //新增用户数
        sheet1.getRow(3).getCell(6).setCellValue(businessDataVO.getNewUsers());
        //有效订单
        sheet1.getRow(4).getCell(2).setCellValue(businessDataVO.getValidOrderCount());
        //平均客单价
        sheet1.getRow(4).getCell(6).setCellValue(businessDataVO.getUnitPrice());
        //(5)完成部分3的内容声明 计算从startDate开始的每一天的营业数据
        for (int rowIndex = 7; rowIndex < 37; rowIndex++, startDate = startDate.plusDays(1)) {
            //基于rowIndex获取本次要填充数据的行索引,每循环一次说明填充了一行,++之后就可以获取下一行
            XSSFRow thisRow = sheet1.getRow(rowIndex);
            BusinessDataVO thisDayBusinessData = workSpaceService.selectBusinessData(LocalDateTime.of(startDate, LocalTime.MIN), LocalDateTime.of(startDate, LocalTime.MAX));
            thisRow.getCell(1).setCellValue(dateTimeFormatter.format(startDate)); //日期
            thisRow.getCell(2).setCellValue(thisDayBusinessData.getTurnover()); //当天营业额
            thisRow.getCell(3).setCellValue(thisDayBusinessData.getValidOrderCount()); //有效订单数
            thisRow.getCell(4).setCellValue(thisDayBusinessData.getOrderCompletionRate()); //订单完成率
            thisRow.getCell(5).setCellValue(thisDayBusinessData.getUnitPrice()); //平均客单价
            thisRow.getCell(6).setCellValue(thisDayBusinessData.getNewUsers()); //新增用户数
        }
        //(6)获取响应对象的输出流 并且将Excel文件对象写给客户端
        ServletOutputStream os = httpServletResponse.getOutputStream();
        xssfWorkbook.write(os);
        //(7)释放资源
        is.close();
        os.close();
        xssfWorkbook.close();
        }

    }

